<template>
  <dialog ref="dialog" role="dialog" class="modal">
    <div
      class="modal-box overflow-hidden"
      :class="{ 'max-w-screen-lg': large }"
    >
      <!-- header -->
      <div class="mb-4 flex justify-between items-center sticky top-0 bg-base-100 z-[1]">
        <h2 class="text-2xl font-bold">{{ title }}</h2>
        <div v-if="closeButton" @click="hide">
          <button class="btn btn-sm btn-circle btn-ghost">✕</button>
        </div>
      </div>

      <div
        class="overflow-x-hidden overflow-y-auto"
        :style="{ 'max-height': large ? '80vh' : '75vh' }"
      >
        <!-- content -->
        <div
          class="flex flex-col w-full"
          :class="{
            'items-center': contentCenter,
            'gap-4': gap,
          }"
        >
          <slot></slot>
          <slot name="content"></slot>
        </div>

        <!-- footer -->
        <div class="modal-action mt-2" v-if="$slots.footer">
          <slot name="footer"></slot>
        </div>
      </div>

    </div>
    <div
      class="modal-backdrop"
      @click="handleBackdropClick"
    >
      <button class="hover:cursor-default">close</button>
    </div>
  </dialog>
</template>

<script setup lang="ts">
import { ref, onMounted, onBeforeUnmount } from "vue";

interface Props {
  title?: string;
  closeButton?: boolean;
  contentCenter?: boolean;
  gap?: boolean;
  large?: boolean;
  closeOnBackdrop?: boolean;
  preventClose?: boolean;
}

const props = withDefaults(defineProps<Props>(), {
  title: "标题",
  closeButton: true,
  contentCenter: false,
  gap: false,
  large: false,
  closeOnBackdrop: false,
  preventClose: true,
});

const emit = defineEmits<{
  (e: "show"): void;
  (e: "hide"): void;
  (e: "close"): void;
}>();

const dialog = ref<HTMLDialogElement | null>(null);

function show() {
  dialog.value?.classList.add("modal-open");
  emit("show");
}
function hide() {
  dialog.value?.classList.remove("modal-open");
  emit("hide");
  emit("close");
}
function close() {
  hide();
}
function toggle() {
  dialog.value?.classList.toggle("modal-open");
}

const handleEscape = (e: KeyboardEvent) => {
  if (e.key === "Escape" && dialog.value?.open) {
    if (props.preventClose) {
      e.preventDefault();
      return;
    }
    hide();
  }
};

const handleBackdropClick = (e: MouseEvent) => {
  if (!props.closeOnBackdrop) {
    e.preventDefault();
    return;
  }
  hide();
};


onMounted(() => {
  window.addEventListener("keydown", handleEscape);
});

onBeforeUnmount(() => {
  window.removeEventListener("keydown", handleEscape);
});

// 暴露方法给父组件
defineExpose({
  show,
  hide,
  close,
  toggle
});
</script>

<style scoped>
.modal-box {
  transform-origin: center;
  will-change: transform, opacity;
}

.modal-backdrop {
  will-change: opacity;
}
</style>
